﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Diagnostics;
using StorageAbstraction;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace VideoProcessor
{
    internal class VideoConverter
    {
        private StorageSubsystem _sSystem;
        private string _processorExecutable;

        internal VideoConverter()
        {
            string systemContainerName = RoleEnvironment.GetConfigurationSettingValue("SystemContainer");
            string requestContainerName = RoleEnvironment.GetConfigurationSettingValue("RequestContainer");
            string responseContainerName = RoleEnvironment.GetConfigurationSettingValue("ResponseContainer");
            string requestQueueName = RoleEnvironment.GetConfigurationSettingValue("RequestQueue");
            string responseQueueName = RoleEnvironment.GetConfigurationSettingValue("ResponseQueue");
            string currentProcessorBlobName = RoleEnvironment.GetConfigurationSettingValue("CurrentProcessorBlob");
            string connString = RoleEnvironment.GetConfigurationSettingValue("StorageClientAccount");
            this._sSystem = new StorageSubsystem(connString, requestQueueName, responseQueueName, requestContainerName, responseContainerName, systemContainerName);
            this._processorExecutable = this._sSystem.GetProcessor();
        }

        internal void ConvertFile(string inputFileName, Guid taskID)
        {
            string tmpName = string.Format(
                "{0}\\{1}.flv",
                Path.GetTempPath(), inputFileName.Substring(inputFileName.LastIndexOf("\\")+1));
            ProcessStartInfo psi = new ProcessStartInfo();
            psi.FileName = this._processorExecutable;
            psi.Arguments = string.Format(@"-i ""{0}"" -y ""{1}""", inputFileName, tmpName);
            psi.CreateNoWindow = true;
            psi.ErrorDialog = false;
            psi.UseShellExecute = false;
            psi.WindowStyle = ProcessWindowStyle.Hidden;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError = true;
            try
            {
                // Start the process with the info we specified.
                // Call WaitForExit and then the using statement will close.
                using (Process exeProcess = Process.Start(psi))
                {
                    StreamReader output = exeProcess.StandardOutput;
                    StreamReader error = exeProcess.StandardError;
                    exeProcess.WaitForExit();
                    string outString = output.ReadToEnd();
                    string errString = error.ReadToEnd();
                    Trace.WriteLine(outString);
                    Trace.TraceError(errString);
                    byte[] fileBytes = File.ReadAllBytes(tmpName);
                    if (fileBytes.Length > 0)
                    {
                        this._sSystem.SaveOutputFile(
                            fileBytes, 
                            tmpName.Substring(tmpName.LastIndexOf("\\")+1),
                            taskID
                            );
                    }
                }
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
            }
        }

        internal void UpdateProcessor()
        {
            this._processorExecutable = this._sSystem.GetProcessor();
        }

        internal void CheckWork()
        {
            VideoTaskMessage vmsg;
            if (this._sSystem.TryGetTask(out vmsg))
            {
                this.DownloadFileToCovert(vmsg);
            }
        }

        private void DownloadFileToCovert(VideoTaskMessage msg)
        {
            string fileName = string.Format("{0}\\{1}", Path.GetTempPath(), msg.BlobName);
            using (FileStream fs = File.Create(fileName))
            {
                this._sSystem.DownloadRequestFile(msg.BlobName, fs);
            }
            this.ConvertFile(fileName, msg.TaskID);
        }
    }
}
